﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace TrafficSplitter
{
    class Config
    {
        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section,
            string key,string val,string filePath);

        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section,
            string key,string def, StringBuilder retVal,
            int size,string filePath);

        private String filename;
        
        // References to objects
        private ComboBox[] listOfComboboxes;
        private CheckBox[] listOfPersistentCheckboxes;
        private CheckBox[] listOfReconnectCheckboxes;
        private CheckBox automaticallySetupRoutes;
        private CheckBox minimizeToTray;
        private CheckBox minimizeOnStartup;

        // Store loaded values
        private String[] listOfInterfaces;
        private Boolean[] listOfPersistentCheckboxValues;
        private Boolean[] listOfReconnectCheckboxValues;
        private Boolean bMinimize;
        private Boolean bAutoroute;
        private Boolean bMinimizeOnStartup;

        public Config(String filename, ComboBox [] listOfComboboxes, CheckBox [] listOfCheckboxes, CheckBox[] listOfReconnectCheckboxes, CheckBox autoSetup, CheckBox minimize, CheckBox minimizeOnStartup)
        {
            this.filename = filename;
            this.listOfComboboxes = listOfComboboxes;
            this.listOfPersistentCheckboxes = listOfCheckboxes;
            this.listOfReconnectCheckboxes = listOfReconnectCheckboxes;
            this.automaticallySetupRoutes = autoSetup;
            this.minimizeToTray = minimize;
            this.minimizeOnStartup = minimizeOnStartup;
            this.listOfInterfaces = new String[Constants.MAX_INTERFACES];
            this.listOfPersistentCheckboxValues = new Boolean[Constants.MAX_INTERFACES];
            this.listOfReconnectCheckboxValues = new Boolean[Constants.MAX_INTERFACES];
        }

        public void LoadMinimizing()
        {
            bMinimize = LoadCheckbox(minimizeToTray, "Checkboxes", "minimize", "false");
            bMinimizeOnStartup = LoadCheckbox(minimizeOnStartup, "Checkboxes", "minimizeOnStartup", "false");
        }

        public void Load()
        {
            Constants.AppendToLogBuffer(LOG_TYPE.Debug, "Loading configuration file.");
            bAutoroute = LoadCheckbox(automaticallySetupRoutes, "Checkboxes", "autoroute", "false");
            LoadControls(listOfPersistentCheckboxes, listOfPersistentCheckboxValues, "PersistentCheckboxes", "false");
            LoadControls(listOfReconnectCheckboxes, listOfReconnectCheckboxValues, "ReconnectCheckboxes", "false");
            LoadControls(listOfComboboxes, listOfInterfaces, "SelectedInterfaces");
            Constants.FlushLogBuffer();
        }

        public void Load(ref Boolean showBalloon)
        {
            showBalloon = LoadBoolean("Boolean", "showBalloon", "true");
        }

        public void Load(long [][]stats)
        {
            String [] names = new String[]{"Received", "Sent"};
            for (int sr = 0; sr < 2; sr++)
            {
                for (int i = 0; i < Constants.MAX_INTERFACES; i++)
                {
                    StringBuilder temp = new StringBuilder(255);
                    GetPrivateProfileString("Stats", names[sr] + i.ToString(), "0", temp, temp.Capacity, this.filename);
                    try
                    {
                        stats[sr][i] = Convert.ToInt64(temp.ToString());
                    }
                    catch (FormatException)
                    {
                        stats[sr][i] = 0;
                        Constants.AppendToLog(LOG_TYPE.Error, "Failed to load accumulated statistics for " + Constants.INTERFACE_NAMES[i] + " bytes " + names[sr] + " with the value being '" + temp.ToString() + "' - Format Exception");
                    }
                    catch (OverflowException)
                    {
                        stats[sr][i] = 0;
                        Constants.AppendToLog(LOG_TYPE.Error, "Failed to load accumulated statistics for " + Constants.INTERFACE_NAMES[i] + " bytes " + names[sr] + " with the value being '" + temp.ToString() + "' - Overflow Exception");
                    }
                }
            }
            Constants.FlushLogBuffer();
        }

        public String LoadVersion(String filename)
        {
            StringBuilder temp = new StringBuilder(255);
            int ret = GetPrivateProfileString("app", "version", "0.0.0.0", temp, temp.Capacity, filename);
            String tmp = temp.ToString();

            return tmp;
        }

        public void Save(long[][] stats)
        {
            String [] names = new String[]{"Received", "Sent"};
            for (int sr = 0; sr < 2; sr++)
            {
                for (int i = 0; i < Constants.MAX_INTERFACES; i++)
                {
                    WritePrivateProfileString("Stats", names[sr] + i.ToString(), stats[sr][i].ToString(), this.filename);
                }
            }
        }

        public void Save(Boolean showBalloon)
        {
            WritePrivateProfileString("Boolean", "showBalloon", showBalloon.ToString(), this.filename);
        }

        public Boolean HasChanged()
        {
            for (int i = 0; i < Constants.MAX_INTERFACES; i++)
            {
                if (!listOfInterfaces[i].Equals(listOfComboboxes[i].Text, StringComparison.OrdinalIgnoreCase))
                    return true;

                if (listOfPersistentCheckboxValues[i] != listOfPersistentCheckboxes[i].Checked)
                    return true;

                if (listOfReconnectCheckboxValues[i] != listOfReconnectCheckboxes[i].Checked)
                    return true;
            }

            if ((this.bMinimize != this.minimizeToTray.Checked)
                || (this.bAutoroute != this.automaticallySetupRoutes.Checked)
                || (this.bMinimizeOnStartup != this.minimizeOnStartup.Checked))
                return true;
            
            return false;
        }

        public void Save()
        {
            SaveControl(minimizeToTray, ref bMinimize, "minimize");
            SaveControl(automaticallySetupRoutes, ref bAutoroute, "autoroute");
            SaveControl(minimizeOnStartup, ref bMinimizeOnStartup, "minimizeOnStartup");
            SaveControls(listOfComboboxes, listOfInterfaces, "SelectedInterfaces");
            SaveControls(listOfPersistentCheckboxes, listOfPersistentCheckboxValues, "PersistentCheckboxes");
            SaveControls(listOfReconnectCheckboxes, listOfReconnectCheckboxValues, "ReconnectCheckboxes");
        }

        private void SaveControls(CheckBox[] checkboxes, Boolean[] newValues, String key)
        {
            for (int i = 0; i < Constants.MAX_INTERFACES; i++)
            {
                newValues[i] = checkboxes[i].Checked;
                SaveControl(checkboxes[i], newValues[i].ToString(), key);
            }
        }

        private void SaveControls(ComboBox[] comboboxes, String[] newValues, String key)
        {
            for (int i = 0; i < Constants.MAX_INTERFACES; i++)
            {
                newValues[i] = comboboxes[i].Text;
                SaveControl(comboboxes[i], newValues[i], key);
            }
        }

        private void SaveControl(CheckBox checkbox, ref Boolean newValue, String name)
        {
            newValue = checkbox.Checked;
            WritePrivateProfileString("Checkboxes", name, newValue.ToString(), this.filename);
        }

        private void SaveControl(Control component, String value, String key)
        {
            WritePrivateProfileString(key, component.Name, value, this.filename);
        }

        private void LoadControls(CheckBox[] checkboxes, Boolean[] newValues, String key, String defaultValue)
        {
            StringBuilder temp = new StringBuilder(10);
            for (int i = 0; i < Constants.MAX_INTERFACES; i++)
            {
                newValues[i] = LoadCheckbox(checkboxes[i], key, checkboxes[i].Name, defaultValue);
            }
        }

        private void LoadControls(ComboBox[] comboboxes, String[] newValues, String key)
        {
            for (int i = 0; i < Constants.MAX_INTERFACES; i++)
            {
                newValues[i] = LoadComboBox(comboboxes[i], key);
                comboboxes[i].Enabled = true;
            }
        }

        private Boolean LoadCheckbox(CheckBox checkbox, String key, String name, String defaultValue)
        {
            Boolean ret;
            ret = LoadBoolean(key, name, defaultValue);
            checkbox.Checked = ret;
            return ret;
        }

        private Boolean LoadBoolean(String key, String name, String defaultValue)
        {
            Boolean ret;
            StringBuilder temp = new StringBuilder(10);
            GetPrivateProfileString(key, name, defaultValue, temp, temp.Capacity, this.filename);
            ret = Convert.ToBoolean(temp.ToString());
            return ret;
        }

        private String LoadComboBox(ComboBox combobox, String key)
        {
            StringBuilder temp = new StringBuilder(255);
            int ret = GetPrivateProfileString(key, combobox.Name, Constants.NO_INTERFACES, temp, temp.Capacity, this.filename);
            String tmp = temp.ToString();
            foreach (VirtualAdapter adapter in combobox.Items)
            {
                Constants.AppendToLogBuffer(LOG_TYPE.Debug, "Listing '" + adapter.GetEntryName() + "' for the " + combobox.Name + " network");
                if (adapter.Equals(tmp))
                {
                    combobox.SelectedItem = adapter;
                    break;
                }
            }
            if (combobox.SelectedIndex < 0)
            {
                Constants.AppendToLogBuffer(LOG_TYPE.Debug, "Failed to set '" + tmp + "' for the " + combobox.Name + " network");
                combobox.SelectedIndex = 0;
            }
            else
            {
                Constants.AppendToLogBuffer(LOG_TYPE.Debug, "Successfully set '" + tmp + "' for the " + combobox.Name + " network");
            }
            return combobox.Text;
        }
    }
}

